package com.lry.sso.gateway.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.lry.sso.auth.common.constant.LoginAuthorizationConstant;
import com.lry.sso.auth.common.exception.AuthException;
import com.lry.sso.auth.common.util.SessionInfo;
import com.lry.sso.common.exception.SysInvocationException;
import com.lry.sso.common.util.PathUtil;
import com.lry.sso.gateway.config.AuthConfigProperties;
import com.lry.sso.service.redis.service.RedisService;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author 李瑞益
 * @date 2020-02-17 17:28
 */
public class AuthRedisFilter extends ZuulFilter {

    private static final Logger logger = LoggerFactory.getLogger(AuthRedisFilter.class);

    @Autowired
    private AuthConfigProperties authConfigProperties;

    @Autowired
    private RedisService redisService;

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER + 1;
    }

    @Override
    public boolean shouldFilter() {
        return authConfigProperties.getRedisFilter().isEnable();
    }

    @Override
    public Object run() throws ZuulException {
        HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
        HttpServletResponse response = RequestContext.getCurrentContext().getResponse();

        if (this.ignore(request.getRequestURI())) {
            return null;
        }
        Cookie[] cookies = request.getCookies();
        if (cookies == null || cookies.length == 0) {
            throw new SysInvocationException(AuthException.AUTH_FAIL);
        }

        String sessionId = this.getSessionKey(request, LoginAuthorizationConstant.SESSION_ID_KEY);

        if (sessionId == null) {
            logger.info("无sessionId");
            throw new SysInvocationException(AuthException.AUTH_FAIL);
        }
        logger.info("从cookie中获取的sessionId :{}",sessionId);

        String sessionInfoStr = redisService.get(sessionId);
        if (sessionInfoStr == null) {
            logger.info("无session信息（登录信息）");
            throw new SysInvocationException(AuthException.AUTH_FAIL);
        }
        SessionInfo sessionInfo = null;
        try {
            sessionInfo = JSON.parseObject(sessionInfoStr, new TypeReference<SessionInfo>() {
            });
            logger.info("登录信息：{}",sessionInfo);
        } catch (Exception e) {
            logger.info("token（登录信息）无效");
            throw new SysInvocationException(AuthException.AUTH_FAIL);
        }
        if (sessionInfo == null) {
            logger.info("无session信息（登录信息）");
            throw new SysInvocationException(AuthException.AUTH_FAIL);
        }

//        RequestInfoContext.set(sessionInfo);

        return null;
    }

    /**
     * 匹配忽略的地址
     * @param requestURI 请求的API
     * @return true:忽略
     */
    private boolean ignore(String requestURI) {
        return PathUtil.match(requestURI,"/login/**");
    }

    /**
     * 获取cookie中的sessionId
     * @param request 请求
     * @param cookieName cookie保存的key
     * @return cookie保存的sessionId
     */
    private String getSessionKey(HttpServletRequest request,String cookieName) {
        Cookie[] cookies = request.getCookies();
        if (cookies == null) {
            logger.warn("获取到的cookie为null");
            return null;
        }
        for (Cookie cookie : cookies) {
            if (cookie.getName().equals(cookieName)) {
                return cookie.getValue();
            }
        }
        return null;
    }
}
